﻿//===============================================================================
// Microsoft Innovation Centre - Western Europe
// Copyright (c) 2008 Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================
using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Wpf.Events;
using Microsoft.WVB.Silverlight.Infrastructure.Events;

namespace Microsoft.WVB.Silverlight.Infrastructure
{
    #region WindowCommandEventArg
    public class WindowCommandEventArg
    {
        public string Subject { get; set; }
        public WindowCommand Command { get; set; }
        public enum WindowCommand
        {
            Show,
            Close,
            ToggleVisisbility
        };
        public Object Data { get; set; }
    }
    #endregion

    public static class CommandService
    {
        #region WindowCommandSubject
        public static string GetWindowCommandSubject(DependencyObject obj)
        {
            return (string)obj.GetValue(WindowCommandSubjectProperty);
        }

        public static void SetWindowCommandSubject(DependencyObject obj, string value)
        {
            obj.SetValue(WindowCommandSubjectProperty, value);
        }

        public static readonly DependencyProperty WindowCommandSubjectProperty =
            DependencyProperty.RegisterAttached("WindowCommandSubject", typeof(string), typeof(CommandService), new PropertyMetadata(OnWindowCommandSubjectChanged));

        static void OnWindowCommandSubjectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            // Now changed to use EventAggregator from P&P
            string s = e.NewValue.ToString();

            if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(d))
            {
                IEventAggregator aggr = IoC.GetCreate<IEventAggregator>();
                if (d is Button)
                {
                    ((Button)d).Click += new RoutedEventHandler(
                        (sender, evarg) =>
                        {
                            aggr.GetEvent<CompositeSilverlightEvent<WindowCommandEventArg>>().Publish(
                                new WindowCommandEventArg
                                {
                                    Subject = s,
                                    Command = WindowCommandEventArg.WindowCommand.ToggleVisisbility
                                });
                        }
                    );
                }
                if (d is IManagedControl)
                {
                    IManagedControl c = d as IManagedControl;

                    aggr.GetEvent<CompositeSilverlightEvent<WindowCommandEventArg>>().Subscribe(
                            (wea) =>
                            {
                                IoC.GetCreate<ILayoutManager>().ShowControl(c);
                            },
                            ThreadOption.UIThread,
                            true,
                            wea => wea.Command == WindowCommandEventArg.WindowCommand.Show && wea.Subject == s
                        );

                    aggr.GetEvent<CompositeSilverlightEvent<WindowCommandEventArg>>().Subscribe(
                            (wea) =>
                            {
                                c.Control.Visibility = Visibility.Collapsed;
                            },
                            ThreadOption.UIThread,
                            true,
                            wea => wea.Command == WindowCommandEventArg.WindowCommand.Close && wea.Subject == s
                        );

                    aggr.GetEvent<CompositeSilverlightEvent<WindowCommandEventArg>>().Subscribe(
                            (wea) =>
                            {
                                if (c.Control.Visibility == Visibility.Collapsed)
                                {
                                    IoC.Get<ILayoutManager>().ShowControl(c);
                                }
                                else
                                {
                                    c.Control.Visibility = Visibility.Collapsed;
                                }
                            },
                            ThreadOption.UIThread,
                            true,
                            wea => wea.Command == WindowCommandEventArg.WindowCommand.ToggleVisisbility && wea.Subject == s
                        );
                }
            }
        }

        public static void NotifyWindow(string subject, WindowCommandEventArg.WindowCommand command)
        {
            IEventAggregator aggr = IoC.GetCreate<IEventAggregator>();
            aggr.GetEvent<CompositeSilverlightEvent<WindowCommandEventArg>>().Publish(
                new WindowCommandEventArg { Subject = subject, Command = command });
        }

        public static void NotifyWindow(string subject, WindowCommandEventArg.WindowCommand command, object data)
        {

            IEventAggregator aggr = IoC.GetCreate<IEventAggregator>();
            aggr.GetEvent<CompositeSilverlightEvent<WindowCommandEventArg>>().Publish(
                new WindowCommandEventArg { Subject = subject, Command = command, Data = data });
        }

        #endregion

        #region ActionCommand
        public static string GetActionCommand(DependencyObject obj)
        {
            return (string)obj.GetValue(ActionCommandProperty);
        }
        public static void SetActionCommand(DependencyObject obj, string value)
        {
            obj.SetValue(ActionCommandProperty, value);
        }
        public static readonly DependencyProperty ActionCommandProperty =
            DependencyProperty.RegisterAttached("ActionCommand", typeof(string), typeof(CommandService), new PropertyMetadata(OnActionCommandChanged));

        static void OnActionCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            string actioncommandstring = e.NewValue.ToString();
            BaseTrigger trigger = GetDefaultTrigger(d);
            if (null != trigger)
            {
                trigger.Subscribe(d);
                trigger.Triggered += (sender, args) =>
                {
                    //_mediator.NotifyColleagues(actioncommandstring, null);
                    if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(d))
                    {
                        IEventAggregator aggr = IoC.GetCreate<IEventAggregator>();
                        aggr.GetEvent<CompositeSilverlightEvent<string>>().Publish(actioncommandstring);
                    }
                };
            }
        }

        static BaseTrigger GetDefaultTrigger(DependencyObject d)
        {
            //TODO:Build something more intelligent here
            if (d is Button)
                return new ButtonClickTrigger();
            return null;
        }

        public static void RegisterBasicAction(string name, System.Action action)
        {
            IEventAggregator aggr = IoC.GetCreate<IEventAggregator>();
            aggr.GetEvent<CompositeSilverlightEvent<string>>().Subscribe(
                x => action(),
                ThreadOption.PublisherThread,
                true,
                o => o == name
            );
        }

        public static void RegisterBasicAction(string name, System.Action action, ThreadOption threadoption)
        {
            IEventAggregator aggr = IoC.GetCreate<IEventAggregator>();
            aggr.GetEvent<CompositeSilverlightEvent<string>>().Subscribe(
                x => action(),
                threadoption,
                true,
                o => o == name
            );
        }

        public static void RegisterCommand<T>(string name, Command<T> command)
        {
            IEventAggregator aggr = IoC.GetCreate<IEventAggregator>();
            aggr.GetEvent<CompositeSilverlightEvent<string>>().Subscribe(
                x => command.Execute(),
                ThreadOption.PublisherThread,
                true,
                o => o == name
            );
        }

        public static void RegisterCommand<T>(string name, Command<T> command, ThreadOption threadoption)
        {
            IEventAggregator aggr = IoC.GetCreate<IEventAggregator>();
            aggr.GetEvent<CompositeSilverlightEvent<string>>().Subscribe(
                x => command.Execute(),
                threadoption,
                true,
                o => o == name
            );
        }
        #endregion
    }

}
